package com.ruoyi.blog.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import com.ruoyi.blog.domain.BlogArticle;
import com.ruoyi.blog.domain.bo.BlogArticleBo;
import com.ruoyi.blog.domain.bo.BlogContentBo;
import com.ruoyi.blog.domain.export.BlogArticleContentExport;
import com.ruoyi.blog.domain.vo.BlogArticleVo;
import com.ruoyi.blog.mapper.BlogArticleMapper;
import com.ruoyi.blog.service.IBlogArticleService;
import com.ruoyi.blog.service.IBlogContentService;
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.YesOrNoEnum;
import com.ruoyi.common.exception.BaseException;
import com.ruoyi.common.utils.BeanCopyUtils;
import com.ruoyi.common.utils.PageUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 博客文章Service业务层处理
 *
 * @author zhutianyu
 * @date 2021-08-19
 */
@Service
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class BlogArticleServiceImpl
    extends ServicePlusImpl<BlogArticleMapper, BlogArticle, BlogArticleVo>
    implements IBlogArticleService {

  private final IBlogContentService iBlogContentService;

  @Override
  public BlogArticleVo queryById(Long id) {
    BlogArticleVo articleVo = getVoById(id);
    articleVo.setClassifyList(Arrays.asList(articleVo.getClassify().split(",")));
    return articleVo;
  }

  @Override
  public TableDataInfo<BlogArticleVo> queryPageList(BlogArticleBo bo) {
    return PageUtils.buildDataInfo(pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo)));
  }

  @Override
  public List<BlogArticleVo> queryList(BlogArticleBo bo) {
    return listVo(buildQueryWrapper(bo));
  }

  private LambdaQueryWrapper<BlogArticle> buildQueryWrapper(BlogArticleBo bo) {
    Map<String, Object> params = bo.getParams();
    LambdaQueryWrapper<BlogArticle> lqw = Wrappers.lambdaQuery();
    lqw.eq(StrUtil.isNotBlank(bo.getTitle()), BlogArticle::getTitle, bo.getTitle());
    lqw.eq(StrUtil.isNotBlank(bo.getSummary()), BlogArticle::getSummary, bo.getSummary());
    lqw.eq(bo.getLevel() != null, BlogArticle::getLevel, bo.getLevel());
    lqw.eq(bo.getPollCount() != null, BlogArticle::getPollCount, bo.getPollCount());
    lqw.eq(bo.getReadCount() != null, BlogArticle::getReadCount, bo.getReadCount());
    lqw.eq(bo.getCommentCount() != null, BlogArticle::getCommentCount, bo.getCommentCount());
    lqw.eq(bo.getHasDeleted() != null, BlogArticle::getHasDeleted, bo.getHasDeleted());
    List<String> classifyList = bo.getClassifyList();
    if (ArrayUtil.isNotEmpty(classifyList)) {
      lqw.and(
          wrapper ->
              classifyList.forEach(
                  classify -> wrapper.or().like(BlogArticle::getClassify, classify)));
    }
    return lqw;
  }

  @Override
  @Transactional(rollbackFor = RuntimeException.class)
  public Boolean insertByBo(BlogArticleBo bo) {
    StringJoiner stringJoiner = new StringJoiner(",");
    bo.getClassifyList().forEach(stringJoiner::add);
    bo.setClassify(stringJoiner.toString());
    BlogArticle add = BeanUtil.toBean(bo, BlogArticle.class);
    validEntityBeforeSave(add);
    boolean save = save(add);
    String id = add.getId();
    BlogContentBo contentBo = new BlogContentBo();
    contentBo.setId(id);
    Boolean insert = iBlogContentService.insertByBo(contentBo);
    return save && insert;
  }

  @Override
  public Boolean updateByBo(BlogArticleBo bo) {
    BlogArticle update = BeanUtil.toBean(bo, BlogArticle.class);
    validEntityBeforeSave(update);
    return updateById(update);
  }

  /**
   * 保存前的数据校验
   *
   * @param entity 实体类数据
   */
  private void validEntityBeforeSave(BlogArticle entity) {
    // TODO 做一些数据校验,如唯一约束
  }

  @Override
  public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
    if (isValid) {
      validHasDeleted(ids);
      // TODO 做一些业务上的校验,判断是否需要校验
    }
    return removeByIds(ids);
  }

  /**
   * 校验是否展示数据,不展示数据的才可以删除
   *
   * @param ids
   */
  private void validHasDeleted(Collection<Long> ids) {
    LambdaQueryWrapper<BlogArticle> queryWrapper = Wrappers.lambdaQuery();
    queryWrapper.in(BlogArticle::getId, ids).eq(BlogArticle::getHasDeleted, 0);
    if (baseMapper.selectCount(queryWrapper) > 0) {
      throw new BaseException("不能删除展示数据的文章");
    }
  }

  @Override
  public Boolean updateStatus(Long id) {
    BlogArticle article = this.baseMapper.selectById(id);
    Integer hasDeleted = article.getHasDeleted();
    if (hasDeleted == 1) {
      article.setHasDeleted(0);
    } else {
      article.setHasDeleted(1);
    }
    return baseMapper.updateById(article) > 0;
  }

  @Override
  public List<BlogArticleContentExport> articleExport(BlogArticleBo bo) {
    List<BlogArticleContentExport> result = Lists.newArrayList();
    queryList(bo)
        .forEach(
            vo -> {
              BlogArticleContentExport export = new BlogArticleContentExport();
              BeanUtils.copyProperties(vo, export);
              // 数据库字段为'是否删除',默认为'0不删除'
              export.setHasShow(
                  ObjectUtil.equals(export.getHasDeleted(), YesOrNoEnum.YES.getCode())
                      ? YesOrNoEnum.NO.getDesc()
                      : YesOrNoEnum.YES.getDesc());
              export.setContent(iBlogContentService.queryById(export.getId()).getContent());
              result.add(export);
            });
    return result;
  }
}
